template <class T>
class auto_ptr()
{
private:
    T* _ptr;
public:
    auto_ptr(T* ptr=nullptr)
        :_ptr(ptr)
    {

    }
    auto_ptr(auto_ptr<T>& ptr)
        :_ptr(ptr._ptr)
    {
        ptr._ptr=nullptr;
    }
    T* operator->()
    {
        return _ptr;
    }
    T& operator*()
    {
        return *_ptr;
    }
    ~auto_ptr()
    {
        delete _ptr;
    }
};

template <class T>
class uniqueue_ptr()
{
private:
    T* _ptr;
public:
    unique_ptr(T *ptr = nullptr)
        : _ptr(ptr)
    {
        std::cout << "unique_ptr(T* ptr)" << std::endl;
    }

    // 禁止拷贝
    unique_ptr(unique_ptr<T> &up) = delete;
    unique_ptr<T> &operator=(unique_ptr<T> &upd) = delete;

    ~unique_ptr()
    {
           std::cout << "~unique_ptr()" << std::endl;
        delete _ptr;
    }

    T &operator*()
    {
        return *_ptr;
    }
    T *operator->()
    {
        return _ptr;
    }
};

template <class T>
class shared_ptr()
{
private:
    T* _ptr;
    int* _count;
public:
    shared_ptr(T* ptr=nullptr)
        :_ptr(ptr)
        ,_count(new int(1))
    {

    }

    shared_ptr(shared_ptr<T>& ptr)
        :_ptr(ptr._ptr)
        ,_count(ptr._count)
    {
        (*_count)++;
    }

    shared_ptr<T> &operator=(shared_ptr<T>& ptr)
    {
        if(ptr._ptr==_ptr)
        {
            return *this;
        }

        if(--(*_count)==0)
        {
            delete _ptr;
            delete _count;
        }

        _count = sp._count;
        _ptr = sp._ptr;
        (*_count)++;

        return *this;
    }

    ~shared_ptr()
    {
        if(--(*_count)==0)
        {
            delete _ptr;
            delete _count;
        }
    }

    T* operator->()
    {
        return _ptr;
    }
    T& operator*()
    {
        return *_ptr;
    }

    int use_count() const
    {
        return *_count;
    }

    T *get() const
    {
        return _ptr;
    }

};

template <class T>
class weak_ptr()
{
private:
    T* _ptr;
public:
    weak_ptr()
        :_ptr(nullptr)
        {}
    weak_ptr(weak_ptr<T> &ptr)
        :_ptr(ptr._ptr)
        {}
    weak_ptr(shared_ptr<T> &ptr)
        :_ptr(ptr.get())
        {}
    weak_ptr<T> &operator=(weak_ptr<T> &ptr)
    {
        _ptr=pte._ptr;
        return *this;
    }

    weak_ptr<T> &operator=(shared_ptr<T> &ptr)
    {
        _ptr=ptr.get();
        return *this;
    }

    T &operator*()
    {
        return *_ptr;
    }
    T *operator->()
    {
        return _ptr;
    }
};